package com.heima.comment.service.impl;

import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustException;
import com.heima.feigns.UserFeign;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import io.seata.common.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    CommentHotService commentHotService;
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        ResponseResult<ApUser> userResult = userFeign.findUserById(user.getId());
        if (userResult.getCode().intValue() != 0 || userResult.getData() == null) {
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, userResult.getErrorMessage());
        }
        user = userResult.getData();
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setArticleId(dto.getArticleId());
        apComment.setType((short) 0);
        apComment.setContent(dto.getContent());
        apComment.setImage(user.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short) 0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());

        mongoTemplate.save(apComment);
        return ResponseResult.okResult();
    }
    @Autowired
    RedissonClient redisson;
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        RLock lock = redisson.getLock("likes-lock");
        lock.lock();
        ApComment apComment;
        try {
            apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (apComment == null) {
                CustException.cust(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST, "未发现评论信息");
            }
            int operation = dto.getOperation().intValue();
            Query query = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId()));
            if (operation == 0) {
                ApCommentLike apCommentLike;
            //    ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
           //     if (apCommentLike != null) {
             //       CustException.cust(AppHttpCodeEnum.DATA_EXIST, "请勿重复点赞");
             //   }
                apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(user.getId());
                apCommentLike.setCommentId(dto.getCommentId());
                apCommentLike.setOperation((short) 0);
                mongoTemplate.save(apCommentLike);
                apComment.setLikes(apComment.getLikes() + 1);
                mongoTemplate.save(apCommentLike);
                if(apComment.getLikes().intValue()>10&&apComment.getFlag().intValue()==0){
                commentHotService.hotCommentExecutor(apComment);
                }

            } else {
                mongoTemplate.remove(query, ApCommentLike.class);
                apComment.setLikes(apComment.getLikes() < 1 ? 0 : apComment.getLikes() - 1);
                mongoTemplate.save(apComment);
            }
        } finally {
            lock.unlock();
        }
        Map map = new HashMap<>();
        map.put("likes", apComment.getLikes());
        return ResponseResult.okResult(map);
    }

    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        if (dto.getMinDate() == null) {
            dto.setMinDate(new Date());
        }
        if (dto.getSize() == null || dto.getSize() < 1) {
            dto.setSize(10);
        }
        List<ApComment> apComments;
        if (dto.getIndex().intValue()==1) {
            Query hotquery = Query.query(Criteria.where("article").is(dto.getArticleId())
                   .and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes"));
            apComments = mongoTemplate.find( hotquery, ApComment.class);
           Integer size=  dto.getSize()-apComments.size();
            Query query = getQuery(dto, size);
            List<ApComment>  normalComments = mongoTemplate.find(query, ApComment.class);
            apComments.addAll(normalComments);
        }else{
            Query query = getQuery(dto, dto.getSize());

            apComments = mongoTemplate.find(query, ApComment.class);

        }

        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null || CollectionUtils.isEmpty(apComments)) {
            ResponseResult.okResult(apComments);
        }
        List<String> commentIdList = apComments.stream().map(ApComment::getId).collect(Collectors.toList());
        Query query1 = Query.query(Criteria.where("commentId").in(commentIdList).and("authorId").is(user.getId()));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query1, ApCommentLike.class);
        List<ApCommentVo> commentVoList = new ArrayList<>();
        List<String> likedCommentIds = apCommentLikes.stream().map(ApCommentLike::getCommentId).distinct().collect(Collectors.toList());
        apComments.forEach(apComment -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment, apCommentVo);
            if(likedCommentIds.contains(apComment.getId())){
                apCommentVo.setOperation((short) 0);
            }
          commentVoList.add(apCommentVo);



        });


        return ResponseResult.okResult(commentVoList);
    }

    private Query getQuery(CommentDto dto, Integer size) {
        return Query.query(Criteria.where("article").is(dto.getArticleId())
                .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .limit(size);
    }
}
